﻿using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ForumServer.Forum;
using log4net;
using System.Collections;
using ForumLibrary;

namespace ForumServer
{
    class ForumManager : IForumManager, IObservable
    {
        hashEncode _encode;
        private List<User> _users;
        private List<Forum.Forum> _forums;
        private List<Moderator> _moderators;
        private ILog _logger;
        private List<ForumUser> _usersControllers;
        private const char _delimiter = '~';
        private const string _moderatorPassword = "Cuda";

        public ForumManager()
        {
            _encode = new hashEncode();
            _users = new List<User>();
            _forums = new List<Forum.Forum>();
            _moderators = new List<Moderator>();
            Logger.Logger log = new Logger.Logger("server", "Server");
            _logger = log.getLogger();
            _usersControllers = new List<ForumUser>();
        }

        public List<User> UsersList { get { return _users; } }
        public List<Forum.Forum> ForumList { get { return _forums; } }
        public List<Moderator> ModeratorsList { get { return _moderators; } }

        public override string register(string firstName, string lastName, string username, string password, string email, string phone, bool isModerator)
        {
            string[] parameters = new string[] { firstName, lastName, username, password };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                if (!isModerator)
                {
                    foreach (User u in _users)
                    {
                        if (u.Username.Equals(username))
                        {
                            _logger.Debug("Username " + username + " is not available");
                            return "Username is not available";
                        }
                    }
                    string maskedPassword = _encode.HashEncode(password);
                    _users.Add(new User(username, maskedPassword, email, phone, firstName, lastName));
                }
                else
                {
                    foreach (Moderator m in _moderators)
                    {
                        if (m.Username.Equals(username))
                        {
                            _logger.Debug("Username " + username + " is not available");
                            return "Username is not available";
                        }
                    }
                    string maskedPassword = _encode.HashEncode(password);
                    _moderators.Add(new Moderator(username, maskedPassword, email, phone, firstName, lastName));
                    _users.Add(new Moderator(username, maskedPassword, email, phone, firstName, lastName));
                }
            }
            else
            {
                return checkResult;
            }
            _logger.Info("A user registered with the username: " + username);
            return "Registration Complete";
        }

        public override string getUserDetails(string username)
        {
            string[] parameters = new string[] { username };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                User user = _users.Find(userF => userF.Username.Equals(username));
                if (user != null)
                {
                    string ret = "User details were sent\n";
                    ret += user.FirstName + "\n";
                    ret += user.LastName + "\n";
                    ret += user.EMail.ToString() + "\n";
                    ret += user.LoggedIn.ToString() + "\n";
                    return ret;
                }
            }
            else
            {
                return checkResult;
            }
            return "User doesn't exist";
        }


        public override string login(string username, string password)
        {
            string[] parameters = new string[] { username, password };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                string tUsername = username.ToLower();
                foreach (User u in _users)
                {
                    if (tUsername.Equals(u.Username.ToLower()))
                    {
                        if (_encode.HashEncode(password).Equals(u.Password))
                        {
                            if (u.LoggedIn)
                            {
                                _logger.Debug("The user " + username + " tried to login while he is login");
                                return "User already login";
                            }
                            u.LoggedIn = true;
                            notifyAllUsers(_usersControllers, Message.Login, u.Username);
                            _logger.Info("The user " + username + " logged in");
                            return "Login Complete: Welcome " + u.Username;
                        }
                        else
                        {
                            _logger.Debug("The user " + username + " tried to login with the wrong password");
                            return "Password incorrect";
                        }
                    }
                }
            }
            else
            {
                return checkResult;
            }
            _logger.Debug("The user " + username + " Doesn't exist");
            return "Username doesn't exist";
        }

        public override string moderatorLogin(string username, string password)
        {
            string[] parameters = new string[] { username, password };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                string tUsername = username.ToLower();
                foreach (Moderator m in _moderators)
                {
                    if (tUsername.Equals(m.Username.ToLower()))
                    {
                        if (_encode.HashEncode(password).Equals(m.Password))
                        {
                            m.LoggedIn = true;
                            _logger.Info("The moderator " + username + " logged in");
                            return "Login Complete: Welcome " + m.Username;
                        }
                        else
                        {
                            _logger.Debug("The moderator " + username + " tried to login with the wrong password");
                            return "Password incorrect";
                        }
                    }
                }
            }
            else
            {
                return checkResult;
            }
            _logger.Debug("The user " + username + " Doesn't exist");
            return "Username doesn't exist";
        }

        public override string logout(string username)
        {
            string[] parameters = new string[] { username };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                string tUsername = username.ToLower();
                foreach (User u in _users)
                {
                    if (tUsername.Equals(u.Username.ToLower()))
                    {
                        u.LoggedIn = false;
                        _logger.Info("The user " + username + " logged out");
                        return "Logout successfully";
                    }
                    else
                    {
                        return "Username doesn't exist";
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return null;
        }

        public override string addFriend(string friendAdding, string friendAdded)
        {
            string[] parameters = new string[] { friendAdding, friendAdded };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                User friend1 = _users.Find(user => user.Username.Equals(friendAdding));
                if (friend1 != null)
                {
                    User friend2 = _users.Find(user => user.Username.Equals(friendAdded));
                    if (friend2 != null)
                    {
                        friend1.addFriend(friend2);
                        notifyAllUsers(_usersControllers, Message.FriendAdded, friendAdding);
                        _logger.Info("The user " + friendAdding + " Added " + friendAdded + " as a friend");
                        return "Friend added successfully";
                    }
                    else
                    {
                        _logger.Debug("The user " + friendAdding + " failed to add " + friendAdded + " as a friend. " + friendAdded + " doesn't exist");
                        return "Friend doesn't exist";
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return "Friend doesn't exist";
        }

        public override string removeFriend(string friendRemoving, string friendRemoved)
        {
            string[] parameters = new string[] { friendRemoving, friendRemoved };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                User friend1 = _users.Find(user => user.Username.Equals(friendRemoving));
                if (friend1 != null)
                {
                    User friend2 = _users.Find(user => user.Username.Equals(friendRemoved));
                    if (friend2 != null)
                    {
                        friend1.removeFriend(friend2);
                        _logger.Info("The user " + friendRemoving + " removed " + friendRemoved + " from friends list");
                        return "Friend removed successfully";
                    }
                    else
                    {
                        _logger.Debug("The user " + friendRemoving + " failed to remove " + friendRemoved + " from friends list. " + friendRemoved + " doesn't exist");
                        return "Friend doesn't exist";
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return "Friend doesn't exist";
        }

        public override string addThread(string username, string forumName, string header, string body)
        {
            string[] parameters = new string[] { username, forumName, header, body };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                User user = _users.Find(u => u.Username.Equals(username));
                if (user != null)
                {
                    Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                    if (forum != null)
                    {
                        Forum.Thread thread = new Forum.Thread(header, body, user);
                        forum.addThread(thread);
                        user.addThread(thread);
                        string message = username + " Added the thread " + header + " to the Forum " + forumName;
                        notifyFriends(_usersControllers, Message.Notification, message, username, forumName, header);
                        notifyAllUsers(_usersControllers, Message.ThreadAdded, username, forumName, header);
                        _logger.Info("The user " + username + " added the thread " + "\"" + header + "\"" + " to the forum " + forumName);
                        return "Thread added successfully";
                    }
                    else
                    {
                        return "Forum doesn't exist";
                    }
                }
                else
                {
                    return "User doesn't exist";
                }
            }
            else
            {
                return checkResult;
            }
        }

        public override string editThread(string username, string forumName, string threadName, string header, string body)
        {
            string[] parameters = new string[] { username, forumName, threadName, header, body };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                User user = _users.Find(u => u.Username.Equals(username));
                if (user != null)
                {
                    Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                    if (forum != null)
                    {
                        Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                        if (thread != null)
                        {
                            if (user.Equals(thread.Creator))
                            {
                                thread.Header = header;
                                thread.Content = body;
                                string message = username + " Edited the thread " + threadName + " in the Forum " + forumName;
                                notifyFriends(_usersControllers, Message.Notification, message, username, forumName, threadName);
                                notifyAllUsers(_usersControllers, Message.ThreadEdited, message, username, forumName, threadName);
                                _logger.Info("The user " + username + " edited the thread " + "\"" + header + "\"" + " in the forum " + forumName);
                                return "Thread edited successfully";
                            }
                            else
                            {
                                _logger.Debug("The user " + username + " failed to edit the thread " + "\"" + thread.Header + "\"" + " in the forum " + forumName);
                                return "Cannot edit a thread that you didn't create";
                            }
                        }
                        else
                        {
                            return "Thread doesn't exist";
                        }
                    }
                    else
                    {
                        return "Forum doesn't exist";
                    }
                }
                else
                {
                    return "User doesn't exist";
                }
            }
            else
            {
                return checkResult;
            }
        }

        public override string deleteThread(string username, string forumName, string threadName)
        {
            string[] parameters = new string[] { username, forumName, threadName };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                Moderator moderator = _moderators.Find(u => u.Username.Equals(username));
                if (moderator != null)
                {
                    Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                    if (forum != null)
                    {
                        Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                        if (thread != null)
                        {
                            forum.removeThread(thread);
                            moderator.removeThread(thread);//TODO if exception is thrown, find index and delete by it
                            _logger.Info("The user " + username + " deleted the thread " + "\"" + threadName + "\"" + " from the forum " + forumName);
                            return "Thread removed successfully";
                        }
                        else
                        {
                            return "Thread doesn't exist";
                        }
                    }
                    else
                    {
                        return "Forum doesn't exist";
                    }
                }
                else
                {
                    return "User isn't moderator and can't remove threads";
                }
            }
            else
            {
                return checkResult;
            }
        }

        public override string addPost(string username, string forumName, string threadName, string header, string body)
        {
            string[] parameters = new string[] { username, forumName, threadName, header, body };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                User user = _users.Find(u => u.Username.Equals(username));
                if (user != null)
                {
                    Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                    if (forum != null)
                    {
                        Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                        if (thread != null)
                        {
                            Post p = new Post(header, body, DateTime.Now, user);
                            thread.PostList.Add(p);
                            thread.LastDate = p.TimeStamp;
                            thread.NumOfReplies++;
                            user.replyPost(p);
                            notifyThreadCreator(_usersControllers, Message.PostAdded, username, forumName, threadName);
                            string message = username + " Added a post in the thread " + threadName + " in the forum " + forumName;
                            notifyFriends(_usersControllers, Message.Notification, message, username, forumName, threadName);
                            notifyAllUsers(_usersControllers, Message.PostAdded, username, forumName, threadName);
                            _logger.Info("The user " + username + " added the post " + "\"" + header + "\"" +
                                " in the thread " + threadName + " in the forum " + forumName);
                            return "Post Added successfully";
                        }
                        else
                        {
                            return "Thread doesn't exist";
                        }
                    }
                    else
                    {
                        return "Forum doesn't exist";
                    }
                }
                else
                {
                    return "User doesn't exist";
                }
            }
            else
            {
                return checkResult;
            }
        }

        public override string editPost(string username, string forumName, string threadName, string postName, string newHeader, string newBody)
        {
            string[] parameters = new string[] { username, forumName, threadName, postName, newHeader, newBody };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                User user = _users.Find(u => u.Username.Equals(username));
                if (user != null)
                {
                    Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                    if (forum != null)
                    {
                        Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                        if (thread != null)
                        {
                            Post post = thread.PostList.Find(p => p.Header.Equals(postName));
                            if (post != null)
                            {
                                if (user.Username.Equals(post.User.Username))
                                {
                                    post.Header = newHeader;
                                    post.Content = newBody;
                                    notifyAllUsers(_usersControllers, Message.PostEdited, "", username, forumName, threadName);
                                    _logger.Info("The user " + username + " edited the post " + "\"" + postName + "\"" +
                                    " in the thread " + threadName + " in the forum " + forumName);
                                    return "Post edited successfully";
                                }
                                else
                                {
                                    return "Cannot edit a post that you didn't create";
                                }
                            }
                            else
                            {
                                return "Post doesn't exist";
                            }
                        }
                        else
                        {
                            return "Thread doesn't exist";
                        }
                    }
                    else
                    {
                        return "Forum doesn't exist";
                    }
                }
                else
                {
                    return "User doesn't exist";
                }
            }
            else
            {
                return checkResult;
            }
        }

        public override string deletePost(string username, string forumName, string threadName, string postName)
        {
            string[] parameters = new string[] { username, forumName, threadName, postName };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                User user = _users.Find(u => u.Username.Equals(username));
                if (user != null)
                {
                    Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                    if (forum != null)
                    {
                        Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                        if (thread != null)
                        {
                            Post post = thread.PostList.Find(p => p.Header.Equals(postName));
                            if (post != null)
                            {
                                if (user.Equals(post.User) || user is Moderator)
                                {
                                    thread.PostList.Remove(post);
                                    user.deletePost(post);//TODO if exception is thrown, find index and delete by it
                                    notifyAllUsers(_usersControllers, Message.PostDeleted, "", username, forumName, threadName);
                                    _logger.Info("The user " + username + " deleted the post " + "\"" + postName + "\"" +
                                    " in the thread " + threadName + " in the forum " + forumName);
                                    return "Post removed successfully";
                                }
                                else
                                {
                                    return "Cannot delete a post that you didn't create";
                                }
                            }
                            else
                            {
                                return "Post doesn't exist";
                            }
                        }
                        else
                        {
                            return "Thread doesn't exist";
                        }
                    }
                    else
                    {
                        return "Forum doesn't exist";
                    }
                }
                else
                {
                    return "User doesn't exist";
                }
            }
            else
            {
                return checkResult;
            }
        }

        public override string searchForNewFriend(string searchedUser)
        {
            string[] parameters = new string[] { searchedUser };
            string checkResult = checkValidParameters(parameters);
            string usersFound = "";
            if (checkResult.Equals(""))
            {
                foreach (User u in _users)
                {
                    if (u.Username.ToLower().Contains(searchedUser.ToLower()))
                    {
                        usersFound += u.Username + "\n";
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return usersFound;
        }

        public override string getUsersList()
        {
            string usernames = "";
            foreach (User u in _users)
            {
                usernames += u.Username + "\n";
            }
            return usernames;
        }

        public override bool isPostOwnerOrModerator(String forumName, String threadName, String PostName, String username)
        {

            Forum.Moderator moderator = _moderators.Find(m => m.Username.Equals(username));
            if (moderator != null)
                return true;
            Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
            if (forum != null)
            {
                Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                if (thread != null)
                {
                    Post post = thread.PostList.Find(t => t.Header.Equals(PostName));
                    if (post != null)
                    {
                        return post.User.Username.Equals(username);
                    }
                }
            }
            return false;

        }

        public override bool checkModeratorPassword(string pass)
        {
            return pass.Equals(_moderatorPassword);
        }

        public override string getFriendslist(string username)
        {
            string[] parameters = new string[] { username };
            string checkResult = checkValidParameters(parameters);
            if (checkResult.Equals(""))
            {
                User user = _users.Find(u => u.Username.Equals(username));
                if (user != null)
                {
                    return user.getFriendslist();
                }
                else
                    return null;
            }
            else
            {
                return checkResult;
            }
        }

        public override string getForumsTopics()
        {
            string forumsTopics = "";
            foreach (Forum.Forum f in _forums)
            {
                forumsTopics += f.Topic + "\n";
            }
            return forumsTopics;
        }

        public override string getThreadsHeaders(string forumName)
        {
            string[] parameters = new string[] { forumName };
            string checkResult = checkValidParameters(parameters);
            string threadsHeaders = "";
            if (checkResult.Equals(""))
            {
                Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                if (forum != null)
                {
                    foreach (Forum.Thread t in forum.ThreadList)
                    {
                        threadsHeaders += t.Header + '~';
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return threadsHeaders;
        }

        public string getThreadPosts(string forumName, string threadName)
        {
            string[] parameters = new string[] { forumName, threadName };
            string checkResult = checkValidParameters(parameters);
            string threadPosts = "";
            if (checkResult.Equals(""))
            {
                Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                if (forum != null)
                {
                    Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                    if (thread != null)
                    {
                        thread.NumOfViews++;
                        return thread.getThreadPosts();
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return threadPosts;
        }


        public override string getThreadDetails(string forumName, string threadName)
        {
            string[] parameters = new string[] { forumName, threadName };
            string checkResult = checkValidParameters(parameters);
            string threadDetails = "";
            if (checkResult.Equals(""))
            {
                Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                if (forum != null)
                {
                    Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                    if (thread != null)
                    {
                        thread.NumOfViews++;
                        string res = thread.getThreadDetails();
                        return res;
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return threadDetails;
        }

        public override string getThreadOwner(string forumName, string threadName)
        {
            string[] parameters = new string[] { forumName, threadName };
            string checkResult = checkValidParameters(parameters);
            string threadDetails = "";
            if (checkResult.Equals(""))
            {
                Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                if (forum != null)
                {
                    Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                    if (thread != null)
                    {
                        string res = thread.CreatorName;
                        return res;
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return threadDetails;
        }

        public override string getPostHeaders(string forumName, string threadName)
        {
            string[] parameters = new string[] { forumName, threadName };
            string checkResult = checkValidParameters(parameters);
            string postHeaders = "";
            if (checkResult.Equals(""))
            {
                Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                if (forum != null)
                {
                    Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                    if (thread != null)
                    {
                        foreach (Post p in thread.PostList)
                        {
                            postHeaders += p.Header + '~';
                        }
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return postHeaders;
        }

        public override string getPostsDetails(string forumName, string threadName)
        {
            string[] parameters = new string[] { forumName, threadName };
            string checkResult = checkValidParameters(parameters);
            string postDetails = "";
            if (checkResult.Equals(""))
            {
                Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                if (forum != null)
                {
                    Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                    if (thread != null)
                    {
                        foreach (Post p in thread.PostList)
                        {
                            postDetails += p.Header + '_' + p.Content + _delimiter;
                        }
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return postDetails;
        }

        public override string getPostDetails(string forumName, string threadName, string postName)
        {
            string[] parameters = new string[] { forumName, threadName, postName };
            string checkResult = checkValidParameters(parameters);
            string postDetails = "";
            if (checkResult.Equals(""))
            {
                Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
                if (forum != null)
                {
                    Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
                    if (thread != null)
                    {
                        Post post = thread.PostList.Find(t => t.Header.Equals(postName));
                        if (post != null)
                        {
                            postDetails += post.Header + '~';
                            postDetails += post.Content + '~';
                            postDetails += post.User.Username + '~';
                            postDetails += post.TimeStamp.ToString() + '~';
                        }
                    }
                }
            }
            else
            {
                return checkResult;
            }
            return postDetails;
        }
        public override string deletePost(string username, string forumName, string threadName, string postName, string body)
        {
            return "stub";
        }

        public override void demo()
        {
            //------------------------Create the forum localy on the server------------------------//
            Forum.Forum _forum = new Forum.Forum("Movies", null);
            Forum.Forum _forum2 = new Forum.Forum("Music", null);
            //------------------------Add some threads for testing------------------------//
            Forum.Thread thread3 = new Forum.Thread("Inception", "Best movie of 2010!", new User("etai", "pass", "mail", "number", "etai", "hazan"));
            Forum.Thread thread4 = new Forum.Thread("The Dark Knight", "Best movie of 2008!", new User("chezi", "pass", "mail", "number", "chezi", "Halpert"));
            Forum.Thread thread5 = new Forum.Thread("The king speech", "One of the movies if not the...", new User("cuda", "pass", "mail", "number", "etai", "hazan"));
            _forum.addThread(thread3);
            _forum.addThread(thread4);
            _forum.addThread(thread5);

            Forum.Thread thread1 = new Forum.Thread("Adele", "Adele's 19 and 21 are great albums!", new User("etai", "pass", "mail", "number", "etai", "hazan"));
            Forum.Thread thread2 = new Forum.Thread("Irish", "Irish music is owseme!", new User("chezi", "pass", "mail", "number", "chezi", "Halpert"));
            _forum2.addThread(thread1);
            _forum2.addThread(thread2);

            //User user = new User("Adiel", "password", "Ashrov@mail.com", "123", "Adiel", "Ashrov");
            //User user3 = new User("Etai", "password", "Hazan@mail.com", "123", "Etai", "Hazan");
            //Moderator user4 = new Moderator("Benny", "password", "Mihaeli@mail.com", "123", "Benny", "Mihaeli");
            //User user5 = new User("Chezi", "password", "Halpert@mail.com", "123", "Chezi", "Halpert");

            _forums.Add(_forum);
            _forums.Add(_forum2);
            //_users.Add(user);
            // _users.Add(user3);
            //_users.Add(user5);
            // _moderators.Add(user4);
        }

        public override void subscribe(IObserver observer, string username, bool loginState)
        {
            ForumUser user = new ForumUser(username, observer, loginState);
            if (!_usersControllers.Contains(user))
                _usersControllers.Add(user);
        }

        public override void unsubscribe(string username)
        {
            ForumUser client = _usersControllers.Find(user => user.Username.Equals(username));
            if (client != null)
                _usersControllers.Remove(client);
        }

        public void notifyFriends(List<ForumUser> users, Message messageType, string message, string username = "", string forumName = "", string threadName = "")
        {
            List<IObserver> controllers = new List<IObserver>();
            User userNotifying = _users.Find(u => u.Username.Equals(username));
            List<User> friends = userNotifying.Friends;
            foreach (User friend in friends)
            {
                foreach (ForumUser user in users)
                {
                    if (friend.Username.Equals(user.Username))
                    {
                        controllers.Add(user.Controller);
                        break;
                    }
                }
                
            }
            new System.Threading.Thread(run).Start(new Notify(controllers, messageType, message, username, forumName, threadName));
        }

        public void notifyThreadCreator(List<ForumUser> users, Message messageType, string username = "", string forumName = "", string threadName = "")
        {
            List<IObserver> controllers = new List<IObserver>();
            string notification = username + " Added a post in your thread " + threadName + " in the forum " + forumName;
            Forum.Forum forum = _forums.Find(f => f.Topic.Equals(forumName));
            Forum.Thread thread = forum.ThreadList.Find(t => t.Header.Equals(threadName));
            string threadCreator = thread.Creator.Username;
            foreach (ForumUser user in users)
            {
                if (user.Username.Equals(threadCreator))
                    controllers.Add(user.Controller);
            }
            new System.Threading.Thread(run).Start(new Notify(controllers, messageType, notification, username, forumName, threadName));
        }

        static void notifyAllUsers(List<ForumUser> users, Message messageType, string message, string username = "", string forumName = "", string threadName = "")
        {
            List<IObserver> controllers = new List<IObserver>();
            foreach (ForumUser user in users)
            {
                controllers.Add(user.Controller);
            }
            new System.Threading.Thread(run).Start(new Notify(controllers, messageType, message, username, forumName, threadName));
        }

        static void run(Object obj)
        {
            Notify n = (Notify)obj;
            foreach (IObserver user in n._controllers)
                user.update(n._message, n._notification, n._username, n._forumName, n._threadName);
        }

        private string checkValidParameters(string[] parameters)
        {
            string checkResult = "";
            foreach (string param in parameters)
                if (param.Contains(_delimiter))
                {
                    checkResult = "Fields cannot contain the special character ~";
                    break;
                }
            return checkResult;
        }

        class Notify
        {
            public List<IObserver> _controllers;
            public Message _message;
            public string _notification;
            public string _username;
            public string _forumName;
            public string _threadName;

            public Notify(List<IObserver> controllers, Message message, string notification, string username = "", string forumName = "", string threadName = "")
            {
                _controllers = controllers;
                _notification = notification;
                _message = message;
                _username = username;
                _forumName = forumName;
                _threadName = threadName;
            }
        }
    }

}